package myturtle;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Stack;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;

class Pos {
	public double x;
	public double y;
	public double dir;

	Pos(double x, double y, double dir) {
		this.x = x;
		this.y = y;
		this.dir = dir;
	}	
	/* copy constructor */
	public Pos(Pos p) {
		this(p.x, p.y, p.dir);
	}

	public void set(double x, double y, double dir) {
		this.x = x;
		this.y = y;
		this.dir = dir;
	}
}

class Segment {
	public double x1,y1,x2,y2;
	public Color col;
	
	Segment(double x1, double y1, double x2, double y2, Color col) {
		this.x1 = x1;
		this.y1 = y1;
		this.x2 = x2;
		this.y2 = y2;
		this.col = col;
	}
}

public class Turtle extends JPanel {

	private static final long serialVersionUID = 1L;
	
	Stack<Pos> stack;
	ArrayList<Pos> positions;
	ArrayList<Segment> segments;
	Pos currPos;
	Color col;

	public Turtle() {
		currPos = new Pos(0.0, 0.0, 0.0);
		positions = new ArrayList<Pos>();
		stack = new Stack<Pos>();
		segments = new ArrayList<Segment>();
		col = Color.green;
		positions.add(new Pos(currPos));
	}
	
	public void turn(double angle) {
		double newAngle = (currPos.dir + angle) % 360;
		currPos.set(currPos.x, currPos.y, newAngle);
	}

	public void move(double dist) {
		double newX = currPos.x + dist * Math.cos(currPos.dir);
		double newY = currPos.y + dist * Math.sin(currPos.dir);
		Pos newPos = new Pos(newX, newY, currPos.dir);
		Segment newSeg = new Segment(currPos.x, currPos.y, newX, newY, col);
		
		// set curr pos to new pos
		currPos.set(newPos.x, newPos.y, newPos.dir);

		// add new pos to our list of positions
		positions.add(newPos);
		// add new segment to our list
		segments.add(newSeg);
	}

	public void push() {
		stack.push(new Pos(currPos));
	}

	public void pop() {
		currPos = stack.pop();
	}
	
	public void setColor(float r, float g, float b) {
		this.col = new Color(r,g,b);
	}

	public void init() {

	}

	public void center(Graphics2D g) {
		Dimension dim = getSize();
		g.translate(dim.height/2, dim.width/2);
		g.rotate(3*Math.PI/2);
	}
	
	public void paint(Graphics2D g) {
		//g.setColor(col);
		for (int i = 0; i < segments.size(); i++) {
			g.setColor(segments.get(i).col);
			g.drawLine((int) segments.get(i).x1, (int) segments.get(i).y1, 
					   (int) segments.get(i).x2, (int) segments.get(i).y2);
		} 
	}
	
	public void paintComponent(Graphics g) {
		clear(g);
		Graphics2D g2d = (Graphics2D) g;
		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		center(g2d);
		paint(g2d);

	}

	// super.paintComponent clears offscreen pixmap,
	// since we're using double buffering by default.

	protected void clear(Graphics g) {
		super.paintComponent(g);
	}
	
	public static void draw(Turtle t, int w, int h) {
		WindowUtilities.openInJFrame(t, w, h);
	}

	public static void main(String[] args) {
		Turtle t = new Turtle();
		t.setColor(0.8f,0.1f,0.0f);
		t.push();
		t.move(100.0);
		t.pop();
		t.turn(45);
		t.setColor(0.0f,0.1f,0.9f);
		t.move(30.0);
		
		draw(t, 400, 400);
	}
}


class WindowUtilities {

	public static void setNativeLookAndFeel() {
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		} catch (Exception e) {
			System.out.println("Error setting native LAF: " + e);
		}
	}

	public static JFrame openInJFrame(Container content, int width, int height,
			String title, Color bgColor) {
		JFrame frame = new JFrame(title);
		frame.setBackground(bgColor);
		content.setBackground(bgColor);
		frame.setSize(width, height);
		frame.setContentPane(content);
		frame.addWindowListener(new ExitListener());
		frame.setVisible(true);
		return (frame);
	}

	public static JFrame openInJFrame(Container content, int width, int height,
			String title) {
		return (openInJFrame(content, width, height, title, Color.white));
	}

	public static JFrame openInJFrame(Container content, int width, int height) {
		return (openInJFrame(content, width, height, content.getClass()
				.getName(), Color.white));
	}
}

class ExitListener extends WindowAdapter {
	public void windowClosing(WindowEvent event) {
		System.exit(0);
	}
}
